﻿using System.Web;
using ITM.Modules.SharePointFileExplorer.SharePoint;
using Microsoft.Win32;
using System;

namespace ITM.Modules.SharePointFileExplorer
{
    public class FileExplorerHandler : IHttpHandler
    {
        /// <summary>
        /// Process request
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            if (context.Request.QueryString["path"] == null)
                return;
            // Here get Url|||RelativePath|||SPUserName|||SPPassword|||SPDomain
            string fileUrlAndRelativePath = context.Server.UrlDecode(context.Request.QueryString["path"]);
            string sharepointUrl, fileUrl, username, password, domain;
            // Postprocess 
            ProcessUrlAndPath(fileUrlAndRelativePath, out sharepointUrl, out fileUrl, out username, out password, out domain);
            string fileName = fileUrl.Substring(fileUrl.LastIndexOf('/') + 1);
            SharePointController sharepointController = new SharePointController(username,
                password, domain, sharepointUrl);
            byte[] fileContent = sharepointController.SPGetFileContent(fileUrl);
            if (fileContent == null)
                return;
            WriteFile(fileContent, fileName, context.Response);
        }

        /// <summary>
        /// Helper function 
        /// </summary>
        /// <param name="fileUrlAndRelativePath"></param>
        /// <param name="Url"></param>
        /// <param name="absolutePath"></param>
        /// <param name="encryptSPUser"></param>
        /// <param name="encryptSPPassword"></param>
        /// <param name="spDomain"></param>
        private void ProcessUrlAndPath(string fileUrlAndRelativePath, out string Url, out string absolutePath, out string encryptSPUser,
            out string encryptSPPassword, out string spDomain)
        {
            string[] strArray = fileUrlAndRelativePath.Split(new string[] { "|||" }, StringSplitOptions.None);
            Url = strArray[0];
            absolutePath = strArray[0] + strArray[1];
            encryptSPUser = strArray[2];
            encryptSPPassword = strArray[3];
            spDomain = strArray[4];
        }

        /// <summary>
        /// Write file out to response
        /// </summary>
        /// <param name="content"></param>
        /// <param name="fileName"></param>
        /// <param name="response"></param>
        private void WriteFile(byte[] content, string fileName, HttpResponse response)
        {
            string fileExtension = GetFileExtension(fileName);
            response.Buffer = true;
            response.Clear();
            response.ContentType = GetMIMEType(fileExtension);
            if (fileExtension != ".htm" && fileExtension != ".html" && fileExtension != ".xml")
            {
                response.AddHeader("content-disposition", "attachment; filename=" + fileName);
            }
            response.BinaryWrite(content);
            response.Flush();
            response.End();
        }

        /// <summary>
        /// Helper function
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private string GetFileExtension(string fileName)
        {
            return fileName.Substring(fileName.LastIndexOf('.'));
        }

        /// <summary>
        /// Helper function
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        private string GetMIMEType(string fileExtension)
        {
            string mimeType = "application/unknown";
            RegistryKey regKey = Registry.ClassesRoot.OpenSubKey(fileExtension);
            if (regKey != null)
            {
                object contentType = regKey.GetValue("Content Type");
                if (contentType != null)
                    mimeType = contentType.ToString();
            }
            return mimeType;
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}